// Pardawl - Arduino intrusion alarm with:
//  - Real Time clock - TinyRTC v1.1 - used for automatic activation of alarm during the night and week-ends
//  - PIR motion sensor - 6m range
//  - Ethernet breakout ENC28J60 - used to send iPhone notification 
//      (using app Prowl and ProwlPHP by Xenji - https://github.com/xenji/ProwlPHP )
//  - uses non default libraries tiniRTC and EtherCard
//  Project site: http://www.tecepe.com.br/Pardawl
//  Code repo: https://code.google.com/p/pardawl/
//  History:
//  -  Omar Reis - jun/2014 - v1.0 
//

#include <Wire.h>
#include <DS1307.h>
#include <EtherCard.h>

// Pardawl Configuration section. Edit this to reflect your particular setup and recompile -------------------------------
static byte myip[] = { 192,168,123,125 };            // static ip address of your Arduino Burglar Alarm
static byte gwip[] = { 192,168,123,1 };              // static ip address of local gateway (ex: local router IP)
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x73,0x79,0x61,0x3D,0x32,0x37 };   // Change if using two Pardawls in the same network
//site where your ProwlPHP pages are hosted
const  char website[] PROGMEM = "www.yoursite.com";   // website name www.yoursite.com
static byte hisip[] = { 200,123,123,176 };           // website ip address (static IP corresponding to 'www.yoursite.com')
const  char phpFile[] PROGMEM = "/MySecret/Folder/h6f84s0a2g/myOffice.php";  // secret path for your prowlPHP page 
// (mantain a secret otherwise someone else can trigger false alarms)
float timeAlarmOff=6.0;              // during weekdays, alarm is on before that (and off during business hours)
float timeAlarmOn=21.0;              // during weekdays, alarm is on after that 
// /config --------------------------------------------------------------------------------------------------------------
 
String comdata = "";
int mark=0;    
int  rtc[7];  //store the current time data
byte rr[7];  //store the set time data
int  ledPin =  13; //light pin
//initial light
int  IRSensor = 0;

int pinIRSensor = 3;
// RTC time vars
float theTime = 0;
float timeDisparoAlarm = 0;
int   dayOfWeek = 0;


char strbuf[20];              // string buffer
byte Ethernet::buffer[500];   // tcp/ip receive buffer 

boolean alarmOn = false;      

// called when the client request is complete
static void my_result_cb (byte status, word off, word len) {
  Serial.print("<<< reply ");
  Serial.println((const char*) Ethernet::buffer + off);
}

/*
 about set time using USB (the code that actually calls this is commented, I'm setting time with code in the setup() function
 format: year,month,day,week,hour,min,sec
 example: 14,03,25,02,13,55,10   2014.03.25 tuesday 13:55:10
 ver http://www.dfrobot.com/wiki/index.php/Real_Time_Clock_Module_%28DS1307%29_V1.1_%28SKU:DFR0151%29
 This is a demo of the RBBB running as webserver with the Ether Card
 2010-05-28 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php 
 */

//out date/time to Serial - format yyyy/mm/dd dw hh:min:sec
static void showTime() {
  RTC.get(rtc, true);    // get current time
  Serial.print(rtc[6]);   //y
  Serial.print("/");
  Serial.print(rtc[5]);   //m
  Serial.print("/");
  Serial.print(rtc[4]);   //d
  
  switch (rtc[3]) {
    case 1: Serial.print(" sun "); break;
    case 2: Serial.print(" mon "); break;
    case 3: Serial.print(" tue "); break;
    case 4: Serial.print(" wed "); break; 
    case 5: Serial.print(" thu "); break;
    case 6: Serial.print(" fri "); break;
    case 7: Serial.print(" sat "); break;
    default: Serial.print(" ??  "); 
  }
  Serial.print(rtc[2]);  //hh
  Serial.print(":");
  Serial.print(rtc[1]);  //min
  Serial.print(":");
  Serial.println(rtc[0]); //ss
}

void setup()                 // <------------------------------ setup()
{
  DDRC |= _BV(2) | _BV(3);   // POWER:Vcc Gnd
  PORTC |= _BV(3);           // VCC PINC3
  
  pinMode(ledPin, OUTPUT);      //Arduino UNO inboard LED signals sensor trigger
  
  pinMode (pinIRSensor, INPUT); //PIR Sensor input
  
  //initial serial baudrate
  Serial.begin(9600);
  Serial.println("Pardawl - Arduino intrusion alarm with ");
  Serial.println("realtime clock and iPhone notification");
  Serial.println("by Omar Reis");
  Serial.println("v1.0 build 01");
  
  showTime(); //show RTC date/time
 
  // uncomment below to set time. And change the numbers :)
    //  RTC.stop();                //stop rtc time
    //  RTC.set(DS1307_SEC, 30);   // sec   <--- set time, day of week and date
    //  RTC.set(DS1307_MIN, 47);   // minute
    //  RTC.set(DS1307_HR, 15);    // hour (use 1 to 24)
    //  RTC.set(DS1307_DOW, 2);    // day of week - Sunday=1, Monday=2 etc
    //  RTC.set(DS1307_DATE, 23);  // day
    //  RTC.set(DS1307_MTH, 06);   // month
    //  RTC.set(DS1307_YR, 14);    // year
    //  RTC.start();               // restart rtc time

  // Square wave output. Not sure it is used..   
  //RTC.SetOutput(LOW);
  //RTC.SetOutput(HIGH);
  //RTC.SetOutput(DS1307_SQW1HZ);
  //RTC.SetOutput(DS1307_SQW4KHZ);
  //RTC.SetOutput(DS1307_SQW8KHZ);
  RTC.SetOutput(DS1307_SQW32KHZ);
  
  // inicializa ethernet
  Serial.println("ethernet setup");
  
  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) 
    Serial.println( "Failed to access Ethernet controller");

  Serial.println("ip setup");
  ether.staticSetup(myip, gwip);
  ether.copyIp(ether.hisip, hisip);
  ether.printIp("Server: ", ether.hisip);
  while (ether.clientWaitingGw())
    ether.packetLoop(ether.packetReceive());
  Serial.println("Gateway found. Ready");      // Using the Serial monitor, make sure the gateway is detected on setup()
}

void blinkLED() {
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
}

// alarmLigado = alarmOn() - returns true if not in business hours
boolean alarmLigado() {    
  // return true; //allways on
   boolean fimDeSemana = (dayOfWeek==1) || (dayOfWeek==7);
   boolean deNoite = (theTime<timeAlarmOff) || (theTime>timeAlarmOn);  // during weekdays, alarm is turned on during the night and off during bussiness hours 
   return (deNoite || fimDeSemana);        // result = night or weekend
}

// set clock with serial data (not used here but mantained from TinyRTC sample)
void setClockDateTime() {
  //read serial data to set clock 
  int j = 0;
  while (Serial.available() > 0)  {
    comdata += char(Serial.read());
    delay(2);
    mark = 1;
  }
  //if data is all collected,then parse it
  if (mark == 1) {
    Serial.println(comdata);
    Serial.println(comdata.length());
    //parse data
    for (int i = 0; i < comdata.length() ; i++) {
      //if the byte is ',' jump it,and parse next value
      if (comdata[i] == ',') { j++; }
      else { rr[j] = rr[j] * 10 + (comdata[i] - '0'); }
    }
    comdata = String("");
    RTC.stop();
    RTC.set(DS1307_SEC, rr[6]);
    RTC.set(DS1307_MIN, rr[5]);
    RTC.set(DS1307_HR, rr[4]);
    RTC.set(DS1307_DOW, rr[3]);
    RTC.set(DS1307_DATE, rr[2]);
    RTC.set(DS1307_MTH, rr[1]);
    RTC.set(DS1307_YR, rr[0]);
    RTC.start();
    mark = 0;
  }
}

void loop()   // <------------------------------------ loop()
{
  //get IR sensor input
  // showTime();
  IRSensor = digitalRead(pinIRSensor);
  // Serial.print("IR Sensor:");
  // Serial.println(IRSensor);
  
  //get current time
  RTC.get(rtc, true);
  
  theTime = (float)(rtc[0] + rtc[1]*60.0 + rtc[2]*3600.0)/(3600.0); //seconds --> hrs
  dayOfWeek = rtc[3];
  
  if (IRSensor == 1) { blinkLED(); }  // blink arduino LED on sensor 
  
  alarmOn = (IRSensor == 1) && alarmLigado();
  
  ether.packetLoop(ether.packetReceive()); //receive etehrnet data, if any 
 
  if (alarmOn)  {
    if (timeDisparoAlarm==0) {   
      Serial.print("Movement detected at ");
      showTime();
      timeDisparoAlarm = theTime; 
      Serial.println("\n Notify iPhone via Prowl");
      ether.browseUrl( phpFile, "", website, my_result_cb);
    };
  } else {
    delay(500);
  }
  //resseta alarm apos 10 min
  if (timeDisparoAlarm != 0) {
    if (theTime-timeDisparoAlarm > 0.017) {
      timeDisparoAlarm = 0;
      Serial.print("Alarm rearmed at ");
      showTime();
    }
  }
  
  // the code below (setting date/time using serial) was commented.
  // Using code inside setup function to set RTC
  // uncomment  to set time using serial ...
  // if (Serial.available() > 0) { 
  //   setClockDateTime();
  // }

}

